#include "include/parse.h"

namespace codec {

// 自定义读取函数
int Parse::read_packet(void *opaque, uint8_t *buf, int buf_size) {
  int fd = *(int *)opaque;
  return read(fd, buf, buf_size);
}
// 自定义 seek 函数
int64_t Parse::seek_packet(void *opaque, int64_t offset, int whence) {
  int fd = *(int *)opaque;
  if (whence == AVSEEK_SIZE) return -1;  // 不支持文件大小查询
  return lseek(fd, offset, whence);
}

bool Parse::open() {
  avformat_network_init();
  unsigned char *buffer = static_cast<unsigned char *>(av_malloc(4096));
  avio_ctx_ = avio_alloc_context(buffer, 4096, 0, &fd_, read_packet, nullptr,
                                 seek_packet);

  format_ctx_ = avformat_alloc_context();
  format_ctx_->pb = avio_ctx_;

  if (avformat_open_input(&format_ctx_, nullptr, nullptr, nullptr) != 0) {
    return false;
  }

  if (avformat_find_stream_info(format_ctx_, nullptr) < 0) {
    return false;
  }

  // 查找视频/音频流
  for (unsigned i = 0; i < format_ctx_->nb_streams; i++) {
    if (format_ctx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
      video_stream_index_ = i;
    } else if (format_ctx_->streams[i]->codecpar->codec_type ==
               AVMEDIA_TYPE_AUDIO) {
      audio_stream_index_ = i;
    }
  }

  return (video_stream_index_ != -1 && audio_stream_index_ != -1);
}

void Parse::close() {
  if (format_ctx_) {
    avformat_close_input(&format_ctx_);
    format_ctx_ = nullptr;
  }

  // 2. 释放自定义IO上下文
  if (avio_ctx_) {
    // 先释放内部缓冲区（av_malloc分配）
    av_freep(&avio_ctx_->buffer);
    // 再释放上下文对象
    avio_context_free(&avio_ctx_);
    avio_ctx_ = nullptr;
  }

  // 3. 关闭文件描述符
  if (fd_ != -1) {
    ::close(fd_);
    fd_ = -1;
  }

  // 4. 重置流索引
  video_stream_index_ = -1;
  audio_stream_index_ = -1;
}
AVPacket *Parse::readNextPacket() {
  AVPacket *packet = av_packet_alloc();
  if (av_read_frame(format_ctx_, packet) >= 0) {
    return packet;
  }
  av_packet_free(&packet);
  return nullptr;
}

AVCodecParameters *Parse::getVideoCodecParams() const {
  // 检查是否已解析媒体文件
  if (!format_ctx_ || video_stream_index_ < 0) {
    __android_log_print(ANDROID_LOG_WARN, "Parse",
                        "Video stream not available or not parsed");
    return nullptr;
  }

  // 返回深拷贝的编解码参数（避免外部修改影响内部状态）
  AVCodecParameters *codecpar = avcodec_parameters_alloc();
  if (!codecpar) {
    __android_log_print(ANDROID_LOG_ERROR, "Parse",
                        "Failed to allocate codec parameters");
    return nullptr;
  }

  // 复制原始流参数
  int ret = avcodec_parameters_copy(
      codecpar, format_ctx_->streams[video_stream_index_]->codecpar);
  if (ret < 0) {
    char errbuf[AV_ERROR_MAX_STRING_SIZE];
    av_strerror(ret, errbuf, sizeof(errbuf));
    __android_log_print(ANDROID_LOG_ERROR, "Parse",
                        "Video codecpar copy failed: %s", errbuf);
    avcodec_parameters_free(&codecpar);
    return nullptr;
  }
  return codecpar;
};

AVCodecParameters *Parse::getAudioCodecParams() const {
  // 检查是否已解析媒体文件
  if (!format_ctx_ || video_stream_index_ < 0) {
    __android_log_print(ANDROID_LOG_WARN, "Parse",
                        "Video stream not available or not parsed");
    return nullptr;
  }

  // 返回深拷贝的编解码参数（避免外部修改影响内部状态）
  AVCodecParameters *codecpar = avcodec_parameters_alloc();
  if (!codecpar) {
    __android_log_print(ANDROID_LOG_ERROR, "Parse",
                        "Failed to allocate codec parameters");
    return nullptr;
  }

  // 复制原始流参数
  int ret = avcodec_parameters_copy(
      codecpar, format_ctx_->streams[audio_stream_index_]->codecpar);
  if (ret < 0) {
    char errbuf[AV_ERROR_MAX_STRING_SIZE];
    av_strerror(ret, errbuf, sizeof(errbuf));
    __android_log_print(ANDROID_LOG_ERROR, "Parse",
                        "Video codecpar copy failed: %s", errbuf);
    avcodec_parameters_free(&codecpar);
    return nullptr;
  }
  return codecpar;
};
AVRational Parse::getVideoTimeBase() const {
  // 检查视频流是否存在
  if (video_stream_index_ >= 0 && format_ctx_ &&
      video_stream_index_ < static_cast<int>(format_ctx_->nb_streams)) {
    AVStream *videoStream = format_ctx_->streams[video_stream_index_];
    return videoStream->time_base;  // 返回视频流时间基
  }
  return AVRational{0, 0};  // 无效时间基标识
}

AVRational Parse::getAudioTimeBase() const {
  // 检查音频流是否存在
  if (audio_stream_index_ >= 0 && format_ctx_ &&
      audio_stream_index_ < static_cast<int>(format_ctx_->nb_streams)) {
    AVStream *audioStream = format_ctx_->streams[audio_stream_index_];
    return audioStream->time_base;  // 返回音频流时间基
  }
  return AVRational{0, 0};  // 无效时间基标识
}

}  // namespace codec